import axios from 'axios'

/**
 * @class
 */
class BAxios {
    /**
     * @type { import('axios').AxiosInstance }
     */
    #axios = null
    /**
     * @type { string }
     */
    #uri = ''
    /**
     *
     * @param {import('axios').AxiosInstance} axios
     * @param { string } uri
     */
    constructor (axios, uri) {
      this.#axios = axios
      this.#uri = uri
    }

    /**
     * get request
     * @param {import('axios').AxiosRequestConfig} config
     * @returns
     */
    get (config) {
      return this.#axios.get(this.#uri, config)
    }

    /**
     * post request
     * @param {any} data
     * @param {import('axios').AxiosRequestConfig} config
     * @returns
     */
    post (data, config) {
      return this.#axios.post(this.#uri, data, config)
    }

    /**
     *  post obj to FormData
     * @param {any} data
     * @param {import('axios').AxiosRequestConfig} config
     * @returns
     */
    postForm (data, config) {
      return this.#axios.postForm(this.#uri, data, config)
    }

    /**
     *
     * @param {*} data
     * @param {import('axios').AxiosRequestConfig} config
     */
    put (data, config) {
      return this.#axios.put(this.#uri, data, config)
    }

    /**
     *
     * @param {*} data
     * @param {import('axios').AxiosRequestConfig} config
     */
    putForm (data, config) {
      return this.#axios.putForm(this.#uri, data, config)
    }

    /**
     * @param {import('axios').AxiosRequestConfig} config
     */
    delete (config) {
      return this.#axios.delete(this.#uri, config)
    }
}

/**
 * 创建一个axios实例
 * @type { import('./index').createBAxios }
 */
function createBAxios (config = {}, codoMap = null) {
  const __axios = axios.create(config)
  let isUseCodeMap = false
  /**
   * 状态码映射
   * @type { Map }
   */
  let __CodeMap = null
  if (codoMap !== null) {
    __CodeMap = new Map(Object.entries(codoMap))
    isUseCodeMap = true
  }
  /**
 * @type { (error: import('axios').AxiosError )=>any }
 */
  let reqError = () => {}
  /**
 *
 * @param {(error: import('axios').AxiosError)=>any} callback
 */
  function onReqError (callback) {
    reqError = callback
  }

  __axios.interceptors.request.use(config => {
    // Do something before request is sent
    return config
  }, error => {
    // Do something with request error
    reqError(error)/*  */
    if (!config?.offError) {
      return Promise.reject(error)
    }
  })

  /** response hook
 * @type { (error: import('axios').AxiosError )=>any }
 */
  let resError = () => {}
  /**
   *
   * @param {(error: import('axios').AxiosError )=>any} callback
   */
  function onResError (callback) {
    resError = callback
  }

  /**
   * 错误映射回调
   * @type { (msg:string)=>any }
   */
  let errMsg = () => {}

  /**
   * 错误映射回调转配
   * @param { (msg:string)=>any } callback
   */
  function onErrMsg (callback) {
    errMsg = callback
  }

  /**
   * 成功映射回调
   * @type { (msg:string)=>any }
   */
  let succMsg = () => {}

  /**
   * 错误映射回调转配
   * @param { (msg:string)=>any } callback
   */
  function onSuccMsg (callback) {
    succMsg = callback
  }
  __axios.interceptors.response.use(response => {
    // Do something before response is sent
    const data = response.data
    if (isUseCodeMap) {
      if (data?.data?.code > (config?.codeErrMin || 300)) {
        const err = __CodeMap.get(data.data.code)
        if (err !== undefined) {
          errMsg(__CodeMap.get(data.data.code), data.data.code)
        }
      } else {
        const err = __CodeMap.get(data.data.code)
        if (err !== undefined) {
          succMsg(__CodeMap.get(data.data.code), data.data.code)
        }
      }
      return data.data
    } else {
      return data
    }
  }, error => {
    // Do something with response error
    resError(error)
    if (!config?.offError) {
      return Promise.reject(error)
    }
  })
  /**
   * 预定义一个请求
   * @param { string } uri
   */
  function createRequest (uri = '') {
    return new BAxios(__axios, uri)
  }
  createRequest.onReqError = onReqError
  createRequest.onResError = onResError
  createRequest.onErrMsg = onErrMsg
  createRequest.onSuccMsg = onSuccMsg
  Object.freeze(createRequest)
  return createRequest
}


export { createBAxios }
